<?php
namespace App\Handlers;

use App;
use App\Jobs\SendHeartBeat;
use App\Utils\CRC16;
use App\Services\Product\DeviceService;
use Cache;
use Carbon\Carbon;
use Exception;
use Illuminate\Foundation\Bus\DispatchesJobs;

class SwooleHandler{
	use DispatchesJobs;

	private $_heartBeatData;

	public function _construct()
	{
		
	}

	/**
	 * tcp 连接开始
	 * @param   $serv 
	 * @return        
	 */
	public function onStart($serv)
	{

	}

	/**
	 * tcp 连接
	 * @param   $serv    
	 * @param   $fd      
	 * @param   $from_id 
	 * @return           
	 */
	public function onConnect($serv, $fd, $from_id)
	{
		try{
			$this->_heartBeatData = pack("v5C3V2v", 0x00bb, 0x0006, 0x0000, 0x000D, 0x0002, 0x12, 0x00, 0x00, 0X00000000, 0X00000000, 0x4FE5);
			
			if($serv->connection_info($fd)['server_port'] == env('WEB_PORT')){
		       	$job = (new SendHeartBeat($fd))->delay(3)->onQueue('heartBeat');
		       	$this->dispatch($job);
			}
			
		}catch(Exception $e){
			logger(['SwooleHandler@onConnect' => [
				'line' => $e->getLine(),
				'file' => $e->getFile(),
				'message' => $e->getMessage(),
				]]);
		}
	}

	/**
	 * tcp 连接接受到消息
	 * @param   $serv    
	 * @param   $fd      
	 * @param   $from_id 
	 * @param   $data    
	 * @return           
	 */
	public function onReceive($serv, $fd, $from_id, $data)
	{
		$this->handle($serv, $data, $fd);
	}

	/**
	 * tcp 关闭
	 * @param   $serv    
	 * @param   $fd      
	 * @param   $from_id 
	 * @return           
	 */
	public function onClose($serv, $fd, $from_id)
	{
		// echo "close -> fd:$fd, from_id:$from_id\n";
		$fds = [];
		foreach($serv->connections as $connection) {
			if($connection != $fd){
				$fds[] = $connection;
			}
		}
		Cache::put('fds', $fds, Carbon::now()->addMinutes(60));
	}

	/**
	 * 缓存连接
	 * @param   $serv 
	 * @return        
	 */
	public function cacheFds($serv)
	{
		$fds = [];
		foreach($serv->connections as $fd) {
			$fds[] = $fd;
		}
		Cache::put('fds', $fds, Carbon::now()->addMinutes(60));
	}

	public function handle($serv, $data, $fd)
	{
		try{
			$result = false;
			if(strlen($data) >= 30) {
				$len = 56;
				$subData = substr($data, 0, $len);
		    	$result = CRC16::check(substr($subData, 4, strlen($subData) - 6), substr($subData, strlen($subData) - 2));
			}
			if($result){
		    	$u = unpack("vflag/vcmd/vcmdStatus/vdataLen/vdataCmd",$subData);
	            
	            if($u['flag'] == 0xbb && $u['cmd'] == 0x8007 && $u['dataLen'] == 46) {            
	                (new DeviceService())->handle($u['dataCmd'], $fd, $subData);
	                $this->cacheFds($serv);
	            }

				$serv->send($fd, $this->_heartBeatData);
				
				$unhandleData = substr($data, $len);
				if(substr_count(bin2hex($unhandleData), 'bb000780') > 0){
					$this->handle($serv, $unhandleData, $fd);
				}
			}
		}catch(Exception $e){
			logger(['SwooleHandler@onReceive' => [
				'line' => $e->getLine(),
				'file' => $e->getFile(),
				'message' => $e->getMessage(),
				]]);
		}
	}


	

}